package cn.openea.perpartner.payment.web.points.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.openea.perpartner.common.core.utils.Arith;
import cn.openea.perpartner.payment.web.points.dto.PointsDto;
import cn.openea.perpartner.payment.web.points.dto.PointsVo;
import cn.openea.perpartner.payment.web.points.entity.Freeze;
import cn.openea.perpartner.payment.web.points.entity.Points;
import cn.openea.perpartner.payment.web.points.mapper.PointsMapper;
import cn.openea.perpartner.payment.web.points.service.IAddPointsService;
import cn.openea.perpartner.payment.web.points.service.IFreezeService;
import cn.openea.perpartner.payment.web.points.service.IPointsService;
import cn.openea.perpartner.payment.web.points.service.ISubPointsService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * @author Weird077
 * @description TODO
 * @date 2022-02-08 22:14
 */
@Service
public class PointsServiceImpl extends ServiceImpl<PointsMapper, Points> implements IPointsService {

    @Autowired
    private IAddPointsService addPointsService;
    @Autowired
    private ISubPointsService subPointsService;
    @Autowired
    private IFreezeService freezeService;


    @Override
    public PointsVo getUserPoints(PointsDto pointsDto) {
        PointsVo pointsVo = new PointsVo();
        //构建查询条件
        LambdaQueryWrapper<Points> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Points::getUserId, pointsDto.getUserId());
        //获取用户积分
        Points points = getOne(wrapper);
        if (BeanUtil.isEmpty(points)) {
            pointsVo.setAllPoints(0);
            pointsVo.setFreePoints(0);
            pointsVo.setAvailablePoints(0);
            pointsVo.setUsedPoints(0);
            return pointsVo;
        }
        //用户总积分
        double allPoints = Convert.toDouble(points.getPoints());
        pointsVo.setAllPoints(allPoints);
        //获取用户冻结中的订单列表
        pointsDto.setStatus("1");
        List<Freeze> freezeList = freezeService.selectList(pointsDto);
        //计算冻结中的积分总和
        double freePoints = freezeList.stream().mapToDouble(obj -> Convert.toDouble(obj.getRealPoints())).sum();
        pointsVo.setFreePoints(freePoints);
        //计算可用积分 = 积分余额-冻结积分
        if(allPoints<freePoints){
            pointsVo.setAvailablePoints(0);
        }else {
            double availablePoints = Arith.sub(allPoints, freePoints);
            pointsVo.setAvailablePoints(availablePoints);
        }
        //计算已使用积分
        //List<SubPoints> subPointsList = subPointsService.selectList(pointsDto);
        //double usedPoints = subPointsList.stream().mapToDouble(obj -> Convert.toDouble(obj.getPoints())).sum();
        double usedPoints = subPointsService.getUsedPoints(pointsDto.getUserId());
        pointsVo.setUsedPoints(usedPoints);
        return pointsVo;
    }
    @Transactional(rollbackFor = {RuntimeException.class, Error.class})
    @Override
    public boolean add(PointsDto pointsDto) {
        addPointsService.add(pointsDto);
        LambdaQueryWrapper<Points> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Points::getUserId, pointsDto.getUserId());
        Points points = getOne(wrapper);
        //查不到记录，即第一次增加积分时
        if (BeanUtil.isEmpty(points)) {
            points = new Points();
            points.setUserId(pointsDto.getUserId());
            points.setPoints(pointsDto.getPoints());
            return save(points);
        }
        double addPoints = Double.parseDouble(pointsDto.getPoints());
        double allPoints = Double.parseDouble(points.getPoints());
        String totalPoints = String.valueOf(Arith.add(addPoints, allPoints));
        points.setPoints(totalPoints);
        return updateById(points);

    }

    @Override
    public boolean sub(PointsDto pointsDto) {
        //构造查询条件
        LambdaQueryWrapper<Points> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Points::getUserId, pointsDto.getUserId());
        Points points = getOne(wrapper);
        if (BeanUtil.isEmpty(points)) {
            return false;
        }
        //扣除的积分
        double subPoints = Convert.toDouble(pointsDto.getPoints());
        //总积分
        double metaPoints = Convert.toDouble(points.getPoints());
        pointsDto.setStatus("1");
        List<Freeze> freezeList = freezeService.selectList(pointsDto);
        //计算冻结中的积分总和
        double freePoints = freezeList.stream().mapToDouble(obj -> Convert.toDouble(obj.getRealPoints())).sum();
        if (subPoints > Arith.sub(metaPoints,freePoints)) {
            return false;
        }
        points.setPoints(Convert.toStr(Arith.sub(metaPoints, subPoints)));
        subPointsService.save(pointsDto);
        return updateById(points);
    }


    @Override
    public boolean checkPoints(PointsDto pointsDto) {
        //获取用户总积分
        LambdaQueryWrapper<Points> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Points::getUserId, pointsDto.getUserId());
        Points points = getOne(wrapper);
        double allPoints = Convert.toDouble(points.getPoints());
        //获取冻结中的积分
        pointsDto.setStatus("1");
        List<Freeze> freezeList = freezeService.selectList(pointsDto);
        //冻结积分总和
        double freePoints = freezeList.stream().mapToDouble(freeze -> Convert.toDouble(freeze.getRealPoints())).sum();
        return Convert.toDouble(pointsDto.getPoints()) <= Arith.sub(allPoints, freePoints);
    }
    @Transactional(rollbackFor = {RuntimeException.class, Error.class})
    @Override
    public boolean settlement(PointsDto pointsDto) {
        //构造查询条件
        LambdaQueryWrapper<Points> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Points::getUserId, pointsDto.getUserId());
        Points points = getOne(wrapper);
        if (BeanUtil.isEmpty(points)) {
            return false;
        }
        //扣除的积分
        double subPoints = Convert.toDouble(pointsDto.getPoints());
        //总积分
        double metaPoints = Convert.toDouble(points.getPoints());
        if (subPoints > metaPoints) {
            return false;
        }
        points.setPoints(Convert.toStr(Arith.sub(metaPoints, subPoints)));
        subPointsService.save(pointsDto);
        return updateById(points);
    }

    @Override
    public double getCumulativePoints(PointsDto pointsDto) {
        return addPointsService.getCumulativePoints(pointsDto);
    }


}
